#ifndef _XCORNERFINDER_H_
#define _XCORNERFINDER_H_

#include <cv.h>
#include "UtilsConvolve.h"

#ifndef VU_PI
#define VU_PI           3.14159265358979323846
#endif


// http://wscg.zcu.cz/wscg2005/Papers_2005/Short/A43-full.pdf
class  CXCornerFinder
{
public:
    CXCornerFinder();
    ~CXCornerFinder();

    // sets the current image the corner finder works with
    bool SetImage(IplImage * _image);

    // finds all x corners in the window in the currently set image
    // it will put the locations of the x-corners into the points array (not more than maxpoints)
    // it returns the number of found x corners
    // sigma: a gaussian is used to reduce noise and create saddle points at x corners
    // accurate: true => slow but accurate implementation (uses derivatives of gaussian)
    // accurate: false => fast but inaccurate implementation (uses discrete derivatives of gaussian)
    int FindXCorners(
        CvPoint2D32f * _points,		// the points to assign
        int _maxPoints,				// the maximum number of points
        bool _accurate,				// the quality of search (discrete vs. direct diveratives)
        vuRect _window,				// the subwindow to search
        float * _score = NULL,		// array that contains score (s value) of the x corner points
        bool _recalc = true
	);

    // same as above but searches entire image
    int FindXCorners(
        CvPoint2D32f * _points,
        int _maxPoints,
        bool _accurate,
        float * _score = NULL,		// array that contains score (s value) of the x corner points
        bool _recalc = true
	);

    // finds the nearest x corner for each point in the local neighbourhood
    // if none is found, point is not changed
    void FindNearestXCorner(
        CvPoint2D32f * _points,		// the points
        int _length,				// the number of points
        bool _accurate,
        CvSize _neighbourhood,		// the neighbourhood to look in for the x corner
        bool * _found = NULL,		// array that will hold whether an x corner was actually found (for each point)
        bool _recalc = true
	);

    // returns the edge support between two points in the image
    // Assumption: the image has already been processed to find x corners (otherwise there is no edge weight)
    float GetEdgeSupport(CvPoint2D32f point1, CvPoint2D32f point2);

    // set sigma value for gaussian blurring
    void SetSigma(double _sigma);
    // set maximum S value
    void SetMaximumSValue(double _maxS);

    // DEBUG: copies S into the image
    void GetSImage(IplImage * _image);

private:
    void ResetImageData();
    void ResetKernelData();
    bool SetImageData(IplImage * _image);
    bool SetKernelData(double _sigma);
    void CalculateAccurate(vuRect & _rect);
    void CalculateDiscrete(vuRect & _rect);

private:
    bool m_smoothed;

    double m_sigma;
    int m_kernelLength;

    double m_maxS;

    float * m_xKernel;
    float * m_dxKernel;
    float * m_dxxKernel;

    IplImage * m_imgCurr;
    IplImage * m_imgSmooth;
    IplImage * m_imgFx;
    IplImage * m_imgFy;
    IplImage * m_imgFxx;
    IplImage * m_imgFxy;
    IplImage * m_imgFyy;
    IplImage * m_imgS;
    IplImage * m_imgTmp;
};

#endif // _XCORNERFINDER_H_
